package xin.marcher.module.lifecycle.repository;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.Lists;
import org.springframework.stereotype.Repository;
import xin.marcher.framework.common.util.data.DataCuttingUtil;
import xin.marcher.module.common.constants.construction.ProductConstants;
import xin.marcher.module.common.core.PageResult;
import xin.marcher.module.common.enums.YesOrNoEnum;
import xin.marcher.module.common.enums.construction.ProductExceptionCode;
import xin.marcher.module.common.exception.BaseBizException;
import xin.marcher.module.common.exception.CommonErrorCodeEnum;
import xin.marcher.module.common.exception.ProductBizException;
import xin.marcher.module.lifecycle.converter.ProductBadIssuesResultConverter;
import xin.marcher.module.lifecycle.converter.ProductExpriConfigurationConverter;
import xin.marcher.module.lifecycle.converter.ProductExpriDataResultConverter;
import xin.marcher.module.lifecycle.domain.dto.ProductBadIssuesResultDTO;
import xin.marcher.module.lifecycle.domain.dto.ProductExpriConfigurationDTO;
import xin.marcher.module.lifecycle.domain.dto.ProductExpriDataResultDTO;
import xin.marcher.module.lifecycle.domain.entity.ProductBadIssuesResultDO;
import xin.marcher.module.lifecycle.domain.entity.ProductExpriConfigurationDO;
import xin.marcher.module.lifecycle.domain.entity.ProductExpriDataResultDO;
import xin.marcher.module.lifecycle.domain.request.ProductBadIssuesResultRequest;
import xin.marcher.module.lifecycle.domain.request.ProductExpriConfigurationRequest;
import xin.marcher.module.lifecycle.domain.request.ProductExpriDataResultRequest;
import xin.marcher.module.lifecycle.mapper.ProductBadIssuesResultMapper;
import xin.marcher.module.lifecycle.mapper.ProductExpriConfigurationMapper;
import xin.marcher.module.lifecycle.mapper.ProductExpriDataResultMapper;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * 商品考核资源管理
 */
@Slf4j
@Repository
public class ProductExpriRepository {

    /**
     * 商品考核指标数据Mapper
     */
    @Resource
    private ProductExpriDataResultMapper productExpriDataResultMapper;

    /**
     * 商品考核指标数据对象克隆
     */
    @Resource
    private ProductExpriDataResultConverter productExpriDataResultConverter;

    /**
     * 考核指标配置Mapper
     */
    @Resource
    private ProductExpriConfigurationMapper productExpriConfigurationMapper;

    /**
     * 考核指标配置对象克隆
     */
    @Resource
    private ProductExpriConfigurationConverter productExpriConfigurationConverter;

    /**
     * 货品质量问题Mapper
     */
    @Resource
    private ProductBadIssuesResultMapper productBadIssuesResultMapper;

    /**
     * 货品质量问题对象克隆
     */
    @Resource
    private ProductBadIssuesResultConverter productBadIssuesResultConverter;

    /**
     * 分页查询某考核类型下所有生效的考核指标数据
     *
     * @return
     */
    public List<ProductExpriDataResultDTO> listExpriDataResultByPage(Integer assessmentType) {
        // 构造查询条件
        LambdaQueryWrapper<ProductExpriDataResultDO> queryWrapper = Wrappers.lambdaQuery();
        // 是否生效
        queryWrapper.eq(ProductExpriDataResultDO::getIsEffective, YesOrNoEnum.YES.getCode());
        // 是否删除
        queryWrapper.eq(ProductExpriDataResultDO::getDelFlag, YesOrNoEnum.YES.getCode());
        // 考核类型：试销期考核/成熟期考核
        queryWrapper.eq(ProductExpriDataResultDO::getAssessmentType, assessmentType);

        // 分页查询存放数据的总集合
        List<ProductExpriDataResultDO> results = new ArrayList<>();

        int pageNum = 1;
        // 设置每次查询的数据量，最大为200
        int pageSize = ProductConstants.QUERY_ITEM_MAX_COUNT;
        Page<ProductExpriDataResultDO> page = new Page<>(pageNum, pageSize);
        // 查询第一页数据
        Page<ProductExpriDataResultDO> pageResult = productExpriDataResultMapper.selectPage(page, queryWrapper);

        // 判断是否还有数据，还有数据则页码+1继续执行分页查询
        List<ProductExpriDataResultDO> batchResult = pageResult.getRecords();
        try {
            while (pageNum <= pageResult.getPages()) {
                results.addAll(batchResult);
                pageNum += 1;
                page.setCurrent(pageNum);
                pageResult = productExpriDataResultMapper
                        .selectPage(page, queryWrapper);
                batchResult = pageResult.getRecords();
                // 每次循环获取数据后，休眠20ms，避免对数据库造成太大压力
                Thread.sleep(20);
            }
        } catch (InterruptedException e) {
            throw new BaseBizException(ProductExceptionCode.PRODUCT_SQL);
        }

        // 最后一组数据也放入结果集中
        results.addAll(page.getRecords());

        // 转为DTO
        List<ProductExpriDataResultDTO> productExpriDataResultList = productExpriDataResultConverter.listEntityToDTO(results);
        return Objects.isNull(productExpriDataResultList) ? Lists.newArrayList() : productExpriDataResultList;
    }

    /**
     * 新增考核指标数据
     *
     * @param request
     * @return
     */
    public Long saveProductExpriDataResult(ProductExpriDataResultRequest request) {
        // 保存
        ProductExpriDataResultDO productExpriDataResultDO = productExpriDataResultConverter.requestToEntity(request);
        productExpriDataResultDO.initCommon();
        int count = productExpriDataResultMapper.insert(productExpriDataResultDO);
        if (count <= 0) {
            throw new ProductBizException(CommonErrorCodeEnum.SQL_ERROR);
        }
        return productExpriDataResultDO.getId();
    }

    /**
     * 将考核指标数据设置为失效状态
     *
     * @param id 主键
     * @return
     */
    public Boolean invalidExpriDataResult(Long id) {
        ProductExpriDataResultRequest request = new ProductExpriDataResultRequest();
        request.setId(id);
        request.setIsEffective(YesOrNoEnum.NO.getCode());
        return updateProductExpriDataResult(request);
    }

    /**
     * 将考核指标数据设置为失效状态
     *
     * @param itemIdList itemId集合
     * @return
     */
    public Boolean invalidExpriDataResult(List<String> itemIdList) {
        if (CollectionUtils.isEmpty(itemIdList)) {
            return false;
        }

        LambdaUpdateWrapper<ProductExpriDataResultDO> updateWrapper = Wrappers.lambdaUpdate();
        updateWrapper.in(ProductExpriDataResultDO::getItemId, itemIdList);
        updateWrapper.set(ProductExpriDataResultDO::getIsEffective, YesOrNoEnum.NO.getCode());
        int count = productExpriDataResultMapper.update(null, updateWrapper);
        if (count <= 0) {
            throw new ProductBizException(CommonErrorCodeEnum.SQL_ERROR);
        }
        return true;
    }

    /**
     * 修改考核指标信息
     *
     * @param request
     * @return
     */
    public Boolean updateProductExpriDataResult(ProductExpriDataResultRequest request) {
        LambdaQueryWrapper<ProductExpriDataResultDO> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(ProductExpriDataResultDO::getId, request.getId());
        ProductExpriDataResultDO selectResult = productExpriDataResultMapper.selectOne(queryWrapper);
        if (Objects.isNull(selectResult)) {
            throw new ProductBizException("该考核指标数据信息不存在，无法修改");
        }

        ProductExpriDataResultDO productExpriDataResultDO = productExpriDataResultConverter.requestToEntity(request);
        productExpriDataResultDO.initCommon();
        int count = productExpriDataResultMapper.updateById(productExpriDataResultDO);
        if (count <= 0) {
            throw new BaseBizException(ProductExceptionCode.PRODUCT_SQL);
        }
        return true;
    }

    /**
     * 新增考核配置信息
     *
     * @param request
     */
    public Long saveProductExpriConfiguration(ProductExpriConfigurationRequest request) {
        LambdaQueryWrapper<ProductExpriConfigurationDO> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(ProductExpriConfigurationDO::getCategoryId, request.getCategoryId());
        ProductExpriConfigurationDO expriConfigurationDO = productExpriConfigurationMapper.selectOne(queryWrapper);
        if (Objects.nonNull(expriConfigurationDO)) {
            throw new ProductBizException("该品类已存在考核配置记录，不能重复创建");
        }

        // 保存
        expriConfigurationDO = productExpriConfigurationConverter.requestToEntity(request);
        expriConfigurationDO.initCommon();
        int count = productExpriConfigurationMapper.insert(expriConfigurationDO);
        if (count <= 0) {
            throw new ProductBizException(CommonErrorCodeEnum.SQL_ERROR);
        }
        return expriConfigurationDO.getId();
    }

    /**
     * 修改考核配置信息
     *
     * @param request
     * @return
     */
    public Boolean updateProductExpriConfiguration(ProductExpriConfigurationRequest request) {
        LambdaQueryWrapper<ProductExpriConfigurationDO> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(Objects.nonNull(request.getId()), ProductExpriConfigurationDO::getId, request.getId());
        queryWrapper.eq(Objects.nonNull(request.getCategoryId()), ProductExpriConfigurationDO::getCategoryId, request.getCategoryId());
        ProductExpriConfigurationDO selectResult = productExpriConfigurationMapper.selectOne(queryWrapper);
        if (Objects.isNull(selectResult)) {
            throw new ProductBizException("该品类下的考核配置信息不存在，无法修改");
        }

        ProductExpriConfigurationDO expriConfigurationDO = productExpriConfigurationConverter.requestToEntity(request);
        expriConfigurationDO.initCommon();
        int count = productExpriConfigurationMapper.updateById(expriConfigurationDO);
        if (count <= 0) {
            throw new BaseBizException(ProductExceptionCode.PRODUCT_SQL);
        }
        return true;
    }

    /**
     * 查询考核配置信息
     *
     * @param request
     * @return
     */
    public ProductExpriConfigurationDTO getProductExpriConfiguration(ProductExpriConfigurationRequest request) {
        LambdaQueryWrapper<ProductExpriConfigurationDO> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(Objects.nonNull(request.getId()), ProductExpriConfigurationDO::getId, request.getId());
        queryWrapper.eq(Objects.nonNull(request.getCategoryId()), ProductExpriConfigurationDO::getCategoryId, request.getCategoryId());
        return productExpriConfigurationConverter.entityToDTO(productExpriConfigurationMapper.selectOne(queryWrapper));
    }

    /**
     * 分页查询考核配置信息
     *
     * @param request
     * @return
     */
    public PageResult<ProductExpriConfigurationDTO> queryProductExpriConfigurationByPage(ProductExpriConfigurationRequest request) {
        LambdaQueryWrapper<ProductExpriConfigurationDO> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(Objects.nonNull(request.getCategoryId()), ProductExpriConfigurationDO::getCategoryId, request.getCategoryId());
        queryWrapper.eq(Objects.nonNull(request.getAssessmentType()), ProductExpriConfigurationDO::getAssessmentType, request.getAssessmentType());
        queryWrapper.eq(Objects.nonNull(request.getFailTimes()), ProductExpriConfigurationDO::getFailTimes, request.getFailTimes());

        Page<ProductExpriConfigurationDO> page = new Page<>(request.getPageNum(), request.getPageSize());
        Page<ProductExpriConfigurationDO> configurationPage = productExpriConfigurationMapper.selectPage(page, queryWrapper);
        List<ProductExpriConfigurationDTO> records = productExpriConfigurationConverter.listEntityToDTO(configurationPage.getRecords());
        return new PageResult<>(records);
    }

    /**
     * 新增货品质量问题记录
     *
     * @param request
     */
    public Long saveProductBadIssuesResult(ProductBadIssuesResultRequest request) {
        LambdaQueryWrapper<ProductBadIssuesResultDO> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(ProductBadIssuesResultDO::getItemId, request.getItemId());
        ProductBadIssuesResultDO productBadIssuesResultDO = productBadIssuesResultMapper.selectOne(queryWrapper);
        if (Objects.nonNull(productBadIssuesResultDO)) {
            throw new ProductBizException("该商品已存在质量问题记录，不能重复创建");
        }

        // 保存
        productBadIssuesResultDO = productBadIssuesResultConverter.requestToEntity(request);
        productBadIssuesResultDO.initCommon();
        int count = productBadIssuesResultMapper.insert(productBadIssuesResultDO);
        if (count <= 0) {
            throw new ProductBizException(CommonErrorCodeEnum.SQL_ERROR);
        }
        return productBadIssuesResultDO.getId();
    }

    /**
     * 修改货品质量问题记录
     *
     * @param request
     * @return
     */
    public Boolean updateProductBadIssuesResult(ProductBadIssuesResultRequest request) {
        LambdaQueryWrapper<ProductBadIssuesResultDO> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(Objects.nonNull(request.getId()), ProductBadIssuesResultDO::getId, request.getId());
        queryWrapper.eq(Objects.nonNull(request.getItemId()), ProductBadIssuesResultDO::getItemId, request.getItemId());
        ProductBadIssuesResultDO selectResult = productBadIssuesResultMapper.selectOne(queryWrapper);
        if (Objects.isNull(selectResult)) {
            throw new ProductBizException("该商品质量问题记录不存在，无法修改");
        }

        ProductBadIssuesResultDO issuesResultDO = productBadIssuesResultConverter.requestToEntity(request);
        issuesResultDO.initCommon();
        int count = productBadIssuesResultMapper.updateById(issuesResultDO);
        if (count <= 0) {
            throw new BaseBizException(ProductExceptionCode.PRODUCT_SQL);
        }
        return true;
    }

    /**
     * 查询货品质量问题记录
     *
     * @param request
     * @return
     */
    public ProductBadIssuesResultDTO getProductBadIssuesResult(ProductBadIssuesResultRequest request) {
        LambdaQueryWrapper<ProductBadIssuesResultDO> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(ProductBadIssuesResultDO::getId, request.getId());
        queryWrapper.eq(Objects.nonNull(request.getItemId()), ProductBadIssuesResultDO::getItemId, request.getItemId());
        return productBadIssuesResultConverter.entityToDTO(productBadIssuesResultMapper.selectOne(queryWrapper));
    }


    /**
     * 分页查询货品质量问题记录
     *
     * @param request
     * @return
     */
    public PageResult<ProductBadIssuesResultDTO> queryProductBadIssuesResultByPage(ProductBadIssuesResultRequest request) {
        LambdaQueryWrapper<ProductBadIssuesResultDO> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(Objects.nonNull(request.getCategoryId()), ProductBadIssuesResultDO::getCategoryId, request.getCategoryId());
        queryWrapper.eq(Objects.nonNull(request.getItemId()), ProductBadIssuesResultDO::getItemId, request.getItemId());
        queryWrapper.eq(Objects.nonNull(request.getNonConformingProduct()),
                ProductBadIssuesResultDO::getNonConformingProduct, request.getNonConformingProduct());
        queryWrapper.eq(Objects.nonNull(request.getContractIntegrity()),
                ProductBadIssuesResultDO::getContractIntegrity, request.getContractIntegrity());

        Page<ProductBadIssuesResultDO> page = new Page<>(request.getPageNum(), request.getPageSize());
        Page<ProductBadIssuesResultDO> issuesResultPage = productBadIssuesResultMapper.selectPage(page, queryWrapper);
        List<ProductBadIssuesResultDTO> productBadIssuesResultDTOList =
                productBadIssuesResultConverter.listEntityToDTO(issuesResultPage.getRecords());
        return new PageResult<>(productBadIssuesResultDTOList);
    }

    /**
     * 分页查询出categoryIdList对应的考核配置集合
     *
     * @param categoryIdList 品类ID集合
     * @return 考核配置集合
     */
    public List<ProductExpriConfigurationDTO> queryExpriConfigurationByCategoryIdList(List<Integer> categoryIdList, Integer assessmentType) {
        // 考核配置集合
        List<ProductExpriConfigurationDTO> productExpriConfigurationList = new ArrayList<>();
        // 一次最大查询200个数据，多个分页查询,这里做数据切割
        List<List<Integer>> splitList = DataCuttingUtil.dataCuttingString(categoryIdList, ProductConstants.QUERY_ITEM_MAX_COUNT);
        for (List<Integer> categoryIds : splitList) {
            LambdaQueryWrapper<ProductExpriConfigurationDO> queryWrapper = Wrappers.lambdaQuery();
            queryWrapper.in(ProductExpriConfigurationDO::getCategoryId, categoryIds);
            queryWrapper.eq(ProductExpriConfigurationDO::getDelFlag, YesOrNoEnum.YES.getCode());
            queryWrapper.eq(ProductExpriConfigurationDO::getAssessmentType, assessmentType);
            // 分批次查询出categoryIdList对应的考核配置集合
            List<ProductExpriConfigurationDO> configurationResultList = productExpriConfigurationMapper.selectList(queryWrapper);
            if (!CollectionUtils.isEmpty(configurationResultList)) {
                productExpriConfigurationList.addAll(productExpriConfigurationConverter.listEntityToDTO(configurationResultList));
            }
        }
        return productExpriConfigurationList;
    }

    /**
     * 批量查询出itemIdList对应的质量诚信问题数据集合，质量诚信问题数据较小，一般不需要分页查询
     *
     * @param itemIdList 商品ID集合
     * @return 质量诚信问题数据集合
     */
    public List<ProductBadIssuesResultDTO> queryProductBadIssuesResultByItemIdList(List<String> itemIdList) {
        if (CollectionUtils.isEmpty(itemIdList)) {
            return Lists.newArrayList();
        }

        LambdaQueryWrapper<ProductBadIssuesResultDO> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.in(ProductBadIssuesResultDO::getItemId, itemIdList);
        queryWrapper.eq(ProductBadIssuesResultDO::getDelFlag, YesOrNoEnum.YES.getCode());
        List<ProductBadIssuesResultDO> issuesResultList = productBadIssuesResultMapper.selectList(queryWrapper);
        return productBadIssuesResultConverter.listEntityToDTO(issuesResultList);
    }
}
